package hn.cch.common.aspect;


import hn.cch.common.annotation.CheckField;
import hn.cch.common.constant.StringConstant;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Order(value = 5)
@Aspect
@Component
public class AnnotationAspect {

    @Pointcut(value = "@annotation(hn.cch.common.annotation.CheckOwner)")
    public void pointcut() {

    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        Set<String> ids = new HashSet<>();

        Object[] args = proceedingJoinPoint.getArgs();
        // if (proceedingJoinPoint instanceof MethodInvocationProceedingJoinPoint) {
        //     MethodInvocationProceedingJoinPoint methodInvocationProceedingJoinPoint = (MethodInvocationProceedingJoinPoint) proceedingJoinPoint;
        //     methodInvocationProceedingJoinPoint.getTarget();
        // }

        Signature signature = proceedingJoinPoint.getSignature();
        if (signature instanceof MethodSignature) {
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = methodSignature.getMethod();
            Parameter[] parameters = method.getParameters();
            Class<?>[] parameterTypes = method.getParameterTypes();
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
            for (int i = 0; i < method.getParameterCount(); i++) {
                for (Annotation annotation : parameterAnnotations[i]) {
                    if (annotation instanceof CheckField) {
                        Class<?> parameterType = parameterTypes[i];
                        Parameter parameter = parameters[i];
                        if (args.length > i - 1) {
                            Object obj = args[i];
                            if (obj instanceof String) {
                                ids.add((String) obj);
                            }
                        }
                    }
                    if (annotation instanceof RequestBody) {
                        if (args.length > i - 1) {
                            Object object = args[i];
                            Class<?> cls = parameterTypes[i];
                            String name = cls.getName();
                            if (name.startsWith(StringConstant.PACKAGE_PREFIX)) {
                                Field[] fields = cls.getDeclaredFields();
                                for (Field field : fields) {
                                    CheckField checkField = field.getAnnotation(CheckField.class);
                                    if (Objects.nonNull(checkField)) {
                                        field.setAccessible(true);
                                        Object obj = field.get(object);
                                        if (obj instanceof String) {
                                            ids.add((String) obj);
                                        }
                                    }
                                }
                            }

                        }
                    }
                }
            }
        }

        Object result = proceedingJoinPoint.proceed(args);
        return result;
    }
}

